/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package amd.core.calculation;

import Jama.Matrix;
import Jama.SingularValueDecomposition;
import amd.database.ConnectDB;
import amd.database.DbDocument;
import amd.database.DbDocumentSimilarity;
import amd.database.DbTerm;
import amd.database.DbTermDocument;
import amd.database.QueryNoResultException;
import java.util.ArrayList;

/**
 *
 * @author Latifah Dwi Nurachma
 */
public class LsaCalculation {

    public static void calculate(ConnectDB conn){
        try {
            Matrix matrixTfIdf = createMatrixTfIdf(conn);
            SingularValueDecomposition matrixSVD = matrixTfIdf.svd();
            ArrayList<String> listDoc = DbDocument.getAllIdDocuments(conn);

            Matrix reducedV = MatrixReduction.reduceRow(matrixSVD.getV(), 300).transpose();
            Matrix reducedS = MatrixReduction.reduceRowAndColumn(matrixSVD.getS(), 300, 300);

            Matrix matrixVS = reducedV.times(reducedS);
            int nRowCol = matrixTfIdf.getColumnDimension();
            int i = 0;
            int j = i + 1;
            while (i < nRowCol) {
                float[] vectorA = Vector.getRowVector(matrixVS, i);
                String idDoc1 = listDoc.get(i);
                while (j < nRowCol) {
                    String idDoc2 = listDoc.get(j);
                    float[] vectorB = Vector.getRowVector(matrixVS, j);
                    float weightCosine = Math.abs(calculateCosine(vectorA, vectorB));
                    //float weightCosine = calculateCosine(vectorA, vectorB);
                    if (DbDocumentSimilarity.isExist(conn, idDoc1, idDoc2)) {
                        DbDocumentSimilarity.update(conn, idDoc1, idDoc2, weightCosine);
                    } else {
                        DbDocumentSimilarity.insert(conn, idDoc1, idDoc2, weightCosine);
                    }
                    j++;
                }
                i++;
                j = i + 1;
            }
        } catch (Exception ex) {
            System.out.println("- Tidak dapat melakukan perhitungan similarity dokumen: "+ ex.toString());
        }


    }


    private static Matrix createMatrixTfIdf(ConnectDB conn) throws QueryNoResultException{
        int nTerm = DbTerm.getNTerm(conn);
        int nDoc = DbDocument.getNDocument(conn);
        Matrix matrixTfIdf = new Matrix(nTerm, nDoc);
        ArrayList<String> listDoc = DbDocument.getAllIdDocuments(conn);
        ArrayList<String> listTerm = DbTerm.getAllTermContents(conn);

        int i=0, j=0;
        while (i<nTerm){
            String termContent = listTerm.get(i);
            while(j<nDoc){
                String idDoc = listDoc.get(j);
                float weight = 0;
                if(DbTermDocument.isExists(conn, termContent, idDoc)){
                    weight = DbTermDocument.getWeightTermDocument(conn, termContent, idDoc);
                }
                matrixTfIdf.set(i, j, weight);
                j++;
            }
            j=0;
            i++;
        }
        return matrixTfIdf;
    }

    private static float calculateCosine(float[] vectorA, float[] vectorB) {
        float weight = (Vector.innerProduct(vectorA, vectorB))/(Vector.lengthVector(vectorA)*Vector.lengthVector(vectorB));
        return weight;
    }

    
}
